package com.toymate.mqtt.listener;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.toymate.ai.asr.STTFactory;
import com.toymate.ai.llm.LLMFactory;
import com.toymate.common.exception.BusinessException;
import com.toymate.common.utils.PushUtils;
import com.toymate.modules.iot.entity.IotDevice;
import com.toymate.modules.iot.entity.IotMessage;
import com.toymate.modules.iot.entity.IotMessageLog;
import com.toymate.modules.iot.entity.IotRole;
import com.toymate.modules.iot.service.IotDeviceService;
import com.toymate.modules.iot.service.IotMessageLogService;
import com.toymate.modules.iot.service.IotMessageService;
import com.toymate.modules.iot.service.IotRoleService;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.codec.MqttPublishMessage;
import net.dreamlu.iot.mqtt.codec.MqttQoS;
import net.dreamlu.iot.mqtt.core.server.event.IMqttMessageListener;
import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.tio.core.ChannelContext;
import org.tio.utils.hutool.CollUtil;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;

/**
 * 消息监听器
 *
 * @author weirdor (179946422@qq.com)
 * @version v1.0.0
 */
@Slf4j
@Service
public class MqttServerMessageListener implements IMqttMessageListener, SmartInitializingSingleton {

    @Autowired
    private ApplicationContext applicationContext;

    private MqttServerTemplate mqttServerTemplate;

    @Autowired
    private IotMessageLogService messageLogService;

    @Autowired
    private IotDeviceService iotDeviceService;

    @Autowired
    private IotRoleService iotRoleService;

    @Autowired
    @Lazy
    private PushUtils pushUtils;

    @Autowired
    private IotMessageService iotMessageService;


    @Override
    public void onMessage(ChannelContext context, String clientId, String topic, MqttQoS qos, MqttPublishMessage mqttPublishMessage) {
        String message = new String(mqttPublishMessage.getPayload(), StandardCharsets.UTF_8);
        log.info("接收消息主题 : {}", topic);
        log.info("接收消息Qos : {}", qos.value());
        log.info("接收消息内容 : {}", message);
        String[] topicItem = topic.substring(1).split("/");
        String productId = String.valueOf(topicItem[0]);
        String deviceNum = topicItem[1];
        String name = topicItem[2];
        switch (name) {
            case "info":
                reportDevice(productId, deviceNum, message);
                break;
            case "function":
                reportFunction(productId, deviceNum, message);
                break;
            case "play":
                reportPlay(productId, deviceNum, message);
                break;
        }
    }

    /**
     * 播放请求
     *
     * @param productId
     * @param deviceNum
     * @param message
     */
    private void reportPlay(String productId, String deviceNum, String message) {
        try {
            // 解析传入的message字符串为JSONObject，获取播放索引
            JSONObject jsonObject = JSONUtil.parseObj(message);
            int index = jsonObject.getInt("index");
            int num = index + 1;
            IotMessageLog messageLog = messageLogService.getOne(Wrappers.<IotMessageLog>lambdaQuery().eq(IotMessageLog::getProductId, productId).eq(IotMessageLog::getDeviceId, deviceNum).eq(IotMessageLog::getSortNum, num));
            if (messageLog != null) {
                //如果有下一条消息，就播放下一条消息
                pushUtils.play(productId, deviceNum, messageLog.getMessageUrl(), messageLog.getMessageId(), num);
            } else {
                // 如果没有找到有效的消息日志，则播放失败，并清除相关的消息日志
                pushUtils.play(productId, deviceNum, "", "", -1);
                messageLogService.remove(Wrappers.<IotMessageLog>lambdaQuery().eq(IotMessageLog::getDeviceId, deviceNum).eq(IotMessageLog::getProductId, productId).ge(IotMessageLog::getSortNum, index));
            }
        } catch (Exception e) {
            log.error("播放异常", e);
        }
    }

    private void reportFunction(String productId, String deviceNum, String message) {
        JSONObject jsonObject = JSONUtil.parseObj(message);
        String video = jsonObject.getStr("video");
        //根据设备
        IotRole iotRole = iotRoleService.getRoleByDevice(deviceNum);
        if (iotRole == null) {
            throw new BusinessException("设备不存在");
        }
        IotDevice iotDevice = iotDeviceService.getOne(Wrappers.<IotDevice>lambdaQuery().eq(IotDevice::getProductId, productId).eq(IotDevice::getSerialNumber, deviceNum));
        if (iotDevice == null) {
            throw new BusinessException("设备不存在");
        }
        //进行语音识别
        Optional<String> optionalString = STTFactory.build(iotRole).discern(deviceNum, video);
        if (optionalString.isPresent()) {
            log.info("识别到语音为: {}", optionalString.get());
            //删除文件
            FileUtil.del(video);
            messageLogService.remove(Wrappers.<IotMessageLog>lambdaQuery().eq(IotMessageLog::getDeviceId, deviceNum).eq(IotMessageLog::getProductId, productId));
            int maxMessageCount = iotRole.getMaxMessageCount();
            String conversationId = "";
            List<IotMessage> messageLogList = iotMessageService.list(Wrappers.<IotMessage>lambdaQuery().eq(IotMessage::getDeviceId, deviceNum).orderByDesc(IotMessage::getId));
            if (CollUtil.isNotEmpty(messageLogList)) {
                IotMessage messageInfo = messageLogList.get(0);
                conversationId = messageInfo.getConversationId();
//                if (messageLogList.size() < maxMessageCount) {
//                    IotMessage messageInfo = messageLogList.get(0);
//                    conversationId = messageInfo.getConversationId();
//                }
            }
            LLMFactory.build(iotRole).chat(optionalString.get(), deviceNum, conversationId, productId, deviceNum);
        } else {
            log.info("没有识别到语音");
        }

    }

    /**
     * 上报设备信息
     */
    private void reportDevice(String productId, String deviceNum, String message) {
        try {
            //获取设备信息
            JSONObject jsonObject = JSONUtil.parseObj(message);
            //获取设备状态
            int status = jsonObject.getInt("status");
            //获取设备信号强度
            String rssi = jsonObject.getStr("rssi");
            log.info("设备状态：{}，信号强度：{}", status, rssi);
        } catch (Exception e) {
            log.error("接收设备信息，解析数据时异常 message={}", e.getMessage());
        }
    }


    @Override
    public void afterSingletonsInstantiated() {
        // 单利 bean 初始化完成之后从 ApplicationContext 中获取 bean
        mqttServerTemplate = applicationContext.getBean(MqttServerTemplate.class);
    }
}